package excelrept

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm/schema"
)

//ConvertFunc 数据转换函数
type ConvertFunc func(strData string) (interface{}, error)

//Convert2Int 转换数据为Int
func Convert2Int(strData string) (interface{}, error) {
	strData = strings.Trim(strData, " ")
	if strData == "" || strData == "#DIV/0!" || strData == "#REF!" {
		return nil, nil
	}
	data, err := strconv.Atoi(strData)
	if err != nil {
		return nil, fmt.Errorf("%s不是有效的整数！", strData)
	}
	return data, nil
}

//Convert2Float 转换数据为Float
func Convert2Float(strData string) (interface{}, error) {
	strData = strings.TrimSpace(strData)
	if strData == "" || strData == "#DIV/0!" || strData == "#REF!" {
		return nil, nil
	}
	isp := false
	if strings.HasSuffix(strData, "%") {
		strData = strings.TrimRight(strData, "%")
		isp = true
	}
	data, err := strconv.ParseFloat(strData, 64)
	if err != nil {
		return nil, fmt.Errorf("%s不是有效的数值！", strData)
	}
	if isp {
		data = data / 100
	}
	return data, nil
}

//Convert2Bool 转换数据为Bool
func Convert2Bool(strData string) (interface{}, error) {
	strData = strings.TrimSpace(strData)
	strData = strings.ToLower(strData)
	data := false
	if strData == "是" || strData == "t" || strData == "1" || strData == "true" {
		data = true
	}
	return data, nil
}

//Convert2String 转换数据为字符串
func Convert2String(strData string) (interface{}, error) {
	strData = strings.TrimSpace(strData)
	return strData, nil
}

//Convert2Date 转换数据为日期类型
func Convert2Date(strData string) (interface{}, error) {
	strData = strings.TrimSpace(strData)
	if strData == "至今" {
		return nil, nil
	}
	if strData == "" {
		return nil, nil
	}
	rs := []rune(strData)
	rsl := len(rs)
	strData2 := ""
	f := ""
	if rsl > 10 && rs[rsl-1] == 'Z' && rs[10] == 'T' {
		f = time.RFC3339
		strData2 = strData
	}
	if f == "" {
		rs2 := make([]rune, 0, rsl+2)
		index := 0
		for i, r := range rs {
			if r == '.' || r == '/' || r == '年' || r == '月' || r == '-' || r == '日' || r == ' ' || r == ':' || r == '时' || r == '分' || r == '秒' {
				if len(rs[index:i]) == 1 {
					rs2 = append(rs2, '0')
				}
				rs2 = append(rs2, rs[index:i]...)
				if r != '日' && r != '秒' {
					rs2 = append(rs2, '-')
				}
				index = i + 1
			}
		}
		if rsl > index {
			if len(rs[index:rsl]) == 1 {
				rs2 = append(rs2, '0')
			}
			rs2 = append(rs2, rs[index:rsl]...)
		}
		f = "2006-01-02"
		l := len(rs2)
		if l > 10 {
			f = "2006-01-02-15-04-05"
		} else if l == 8 {
			f = "20060102"
			if rs2[2] == '-' {
				f = "01-02-06"
			}
		} else if l < 8 {
			f = "200612"
		}
		strData2 = string(rs2)
		if l == 7 && len(strings.Split(strData2, "-")) == 2 {
			strData2 = strData2 + "-01"
			f = "2006-01-02"
		}
	}
	data, err := time.Parse(f, strData2)
	if err != nil {
		return nil, fmt.Errorf("%s不是有效的日期！", strData)
	}
	return data.Format("2006-01-02"), nil
}

//GetConvertFunc 获取转换函数
func GetConvertFunc(dt schema.DataType) (ConvertFunc, int, error) {
	switch dt {
	case schema.Bool:
		return Convert2Bool, 0, nil
	case schema.Int, schema.Uint:
		return Convert2Int, 0, nil
	case schema.Float:
		return Convert2Float, 0, nil
	case schema.String:
		return Convert2String, 0, nil
	case schema.Time:
		return Convert2Date, 0, nil
	default:
		errInfo := fmt.Sprintf("字段类型%s在导入模块中不支持！", dt)
		return nil, 0, errors.New(errInfo)
	}
}

//Convert 转换值为特定类型
func Convert(tName, cName, valStr string) (val interface{}, err error) {
	dbCols, err := getDBColumns(tName)
	if err != nil {
		return
	}
	for _, dbc := range dbCols {
		if strings.EqualFold(dbc.Name, cName) {
			return dbc.convertFunc(valStr)
		}
	}
	err = fmt.Errorf("表%s中没有找到字段%s", tName, cName)
	return
}
